package com.linkai.JUC._08_pool;

import org.omg.SendingContext.RunTime;

import java.util.concurrent.*;

/**
 * @Description: ThreadPoolExecutor 自定义线程池，4种拒绝策略
 * @Author: 林凯
 * @Date: 2021/10/25 11:06
 */
public class ThreadPoolDemo02 {
    public static void main(String[] args) {
        // 自定义线程池：ThreadPoolExecutor

        /*
            最大线程到底该如何定义
            1. CPU 密集型   几核CPU就是几，保证CPU效率最高
                获取CPU的核心数：Runtime.getRuntime().availableProcessors()
                实际开发中不能写死，需要动态的获取
            2. IO 密集型
                判断你的程序中十分耗IO的线程，代码中设置的要大于这个值，保证还有其他的CPU核心跑其他的任务线程。
                程序，15个大型任务，IO十分占用资源
        * */

        System.out.println(Runtime.getRuntime().availableProcessors());

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                2,
                5,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3),
                Executors.defaultThreadFactory(),
                // 拒绝策略1：阻塞队列满了，还有人进来，不处理这个人的，抛出异常
                new ThreadPoolExecutor.AbortPolicy());

        // 拒绝策略2：哪来的去哪里（这里会抛回给Main线程处理），由调用线程处理，不抛出异常。
        new ThreadPoolExecutor.CallerRunsPolicy();
        // 拒绝策略3：队列满了，丢掉任务，不会抛出异常
        new ThreadPoolExecutor.DiscardPolicy();
        // 拒绝策略4：队列满了，丢弃阻塞队列 workQueue 中最老的一个任务，并将新任务加入，也不会抛出异常
        new ThreadPoolExecutor.DiscardOldestPolicy();

        try {
            for (int i = 1; i <= 9; i++) {
                // 通过线程池之后，使用线程池来创建线程
                // 里面传入一个 Runnable 接口，可以使用 Lambda 表达式
                // 最大承载：Deque + Max
                // 超过了，抛出异常（取决于拒绝策略）：RejectedExecutionException
                threadPoolExecutor.execute(()->{
                    System.out.println(Thread.currentThread().getName() + "ok");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 线程池用完，程序结束
            threadPoolExecutor.shutdown();
        }
    }
}
